<template>
  <div ref="main" :style="{ width: width, height, height }">
    <textarea ref="codeEditor"></textarea>
  </div>
</template>

<script>
// 引入全局实例
import codeMirror from "codemirror";

// 核心样式
import "codemirror/lib/codemirror.css";
// 引入主题后还需要在 options 中指定主题才会生效
import "codemirror/theme/cobalt.css";

// 需要引入具体的语法高亮库才会有对应的语法高亮效果
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/css/css.js";
import "codemirror/mode/xml/xml.js";
import "codemirror/mode/clike/clike.js";
import "codemirror/mode/markdown/markdown.js";
import "codemirror/mode/python/python.js";
import "codemirror/mode/r/r.js";
import "codemirror/mode/shell/shell.js";
import "codemirror/mode/sql/sql.js";
import "codemirror/mode/swift/swift.js";
import "codemirror/mode/vue/vue.js";
// 折叠代码要用到一些玩意
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/foldgutter";
import "codemirror/addon/fold/xml-fold";
import "codemirror/addon/fold/foldcode";
import "codemirror/addon/fold/brace-fold";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/comment-fold.js";

import "codemirror/addon/scroll/annotatescrollbar.js";
import "codemirror/addon/search/matchesonscrollbar.js";
import "codemirror/addon/search/match-highlighter.js";
import "codemirror/addon/search/jump-to-line.js";

import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
export default {
  name: "eip-code",

  props: {
    readOnly: {
      type: Boolean,
      default: false,
    },
    value: {
      type: String,
      default: "",
    },
    width: {
      type: Number,
    },
    height: {
      type: String,
      default: "100%",
    },
    language: {
      type: String,
      default: "application/json",
    },
  },

  data() {
    return {
      editor: null,
      options: {
        mode: "application/json",
        // 缩进格式
        tabSize: 2,
        // 主题，对应主题库 JS 需要提前引入
        theme: "cobalt",
        // 显示行号
        lineNumbers: true,
        line: true,
        gutters: [
          "codeMirror-linenumbers",
          "codeMirror-foldgutter",
          "codeMirror-lint-markers", // codeMirror-lint-markers是实现语法报错功能
        ],
        lineWrapping: true, // 自动换行
        matchBrackets: true, // 括号匹配显示
        autoCloseBrackets: true, // 输入和退格时成对
        readOnly: this.readOnly, // 只读
        foldGutter: true,
        autoRefresh: true,
      },
    };
  },
  mounted() {
    this.editor = codeMirror.fromTextArea(this.$refs.codeEditor, this.options);
    this.editor.setSize("auto", this.height);
    this.editor.setValue(this.value);
  },
  methods: {
    codeMirrorChange() {
      console.log("content1: " + this.value);
      console.log("content2: " + JSON.stringify(this.editor.getValue()));
    },
    autoMarkText() {
      if (this.value) {
        this.autoMark(this.value);
        this.focus(this.value);
      }
    },
    focus(value) {
      this.editor.setCursor({
        line: 0,
        ch: value ? value.length : 0,
      });
      this.editor.focus();
    },
    /**
     * 解析 editor 的内容，分别对表单变量和函数进行标记
     */
    autoMark() {
      const editor = this.editor;
      const lines = editor.lineCount();
      for (let line = 0; line < lines; line++) {
        const content = editor.getLine(line);
        // 标记函数调用,匹配一个或多个连续的大写字母，后面可以有任意数量的空白字符，再紧跟一个左括号
        content.replace(/([A-Z]+)\s*\(/g, (_, func, pos) => {
          this.markText(
            { line: line, ch: pos },
            { line: line, ch: pos + func.length },
            func,
            "cm-func"
          );
          return _;
        });
        // 标记表单变量,这应该是动态获取，自行替换即可
        let vars = ["表单", "表单1", "表单11", "表单12"];
        vars.forEach((v) => {
          let from = 0;
          let idx = -1;
          while (~(idx = content.indexOf(v, from))) {
            this.markText(
              { line: line, ch: idx },
              { line: line, ch: idx + v.length },
              v,
              "cm-field"
            );
            from = idx + v.length;
          }
        });
      }
    },
  },
};
</script>

<style scoped>
/deep/ .margin {
  margin: 0;
}
</style>